package cn.iotab.iotkit.transport.api.access.handler.adaptor;

import cn.iotab.iotkit.transport.api.access.model.custom.ProtocolConstant;
import cn.iotab.iotkit.transport.api.access.model.custom.event.EventMessage;
import cn.iotab.iotkit.transport.api.access.model.custom.firmware.PushUpgradeFirmwareMessage;
import cn.iotab.iotkit.transport.api.access.model.custom.firmware.ReportFirmwareMessage;
import cn.iotab.iotkit.transport.api.access.model.custom.firmware.ReportUpgradeProgressMessage;
import cn.iotab.iotkit.transport.api.access.model.custom.firmware.RequestFirmwareMessage;
import cn.iotab.iotkit.transport.api.access.model.custom.function.FunctionInvokeMessage;
import cn.iotab.iotkit.transport.api.access.model.custom.property.PropertyPushMessage;
import cn.iotab.iotkit.transport.api.access.model.message.CommonDeviceMessage;
import cn.iotab.iotkit.transport.api.access.model.message.DeviceMessageReply;
import cn.iotab.iotkit.transport.api.access.model.message.MessageReplyCodec;
import cn.iotab.iotkit.transport.api.access.model.message.OriginMessage;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;


public class DeviceMessageConverter {

    /**
     * 上行消息解析
     * @param productKey
     * @param deviceId
     * @param msg
     * @return
     */
    public static CommonDeviceMessage convertMessage(String productKey, String deviceId, String msg) {
        JSONObject json = JSON.parseObject(msg);
        OriginMessage message = OriginMessage.fromJson(json);
        message.validate();

        //属性上报
        if (StringUtils.startsWith(message.getType(), ProtocolConstant.PROP_PREFIX)) {
            return buildMessage(productKey, deviceId, message, PropertyPushMessage.class);
        }

        if (StringUtils.startsWith(message.getType(), ProtocolConstant.EVENT_PREFIX)) {
            return buildMessage(productKey, deviceId, message, EventMessage.class);
        }

        if (StringUtils.startsWith(message.getType(), ProtocolConstant.FUNC_PREFIX)) {
            return buildMessage(productKey, deviceId, message, FunctionInvokeMessage.class);
        }

        // firmware
        if (StringUtils.equals(message.getType(), ProtocolConstant.FIRMWARE_PUSH)) {
            return buildMessage(productKey, deviceId, message, PushUpgradeFirmwareMessage.class);
        }
        if (StringUtils.equals(message.getType(), ProtocolConstant.FIRMWARE_REQUEST)) {
            return buildMessage(productKey, deviceId, message, RequestFirmwareMessage.class);
        }
        if (StringUtils.equals(message.getType(), ProtocolConstant.FIRMWARE_REPORT)) {
            return buildMessage(productKey, deviceId, message, ReportFirmwareMessage.class);
        }
        if (StringUtils.equals(message.getType(), ProtocolConstant.FIRMWARE_PROGRESS)) {
            return buildMessage(productKey, deviceId, message, ReportUpgradeProgressMessage.class);
        }

        throw new UnsupportedOperationException("unsupported message.type: " + message.getType());
    }

    @SneakyThrows
    private static <T extends CommonDeviceMessage> T buildMessage(String productKey, String deviceId, OriginMessage message, Class<T> tClass) {
        T msg = tClass.newInstance();
        msg.fromOriginMessage(productKey, deviceId, message);
        return msg;
    }

    @SneakyThrows
    @SuppressWarnings("all")
    public static <T extends DeviceMessageReply> T convertMessageReply(DeviceMessageReply reply, Class<T> tClass) {
        if (reply.getClass().isAssignableFrom(tClass)) {
            return (T) reply;
        }
        if (MessageReplyCodec.class.isAssignableFrom(tClass)) {
            T msg = tClass.newInstance();
            ((MessageReplyCodec) msg).fromOriginMessageReply(reply.getProductKey(), reply.getDeviceId(), reply.toOriginMessageReply());
            return msg;
        }
        throw new ClassCastException("can't cast class " + reply.getClass().getName() + " to " + tClass.getName());
    }
}
